import React, { useEffect, useState } from "react"
import { useSafeAreaInsetsStyle } from "../../utils/useSafeAreaInsetsStyle"
import { View, ViewStyle, Text, StyleSheet, ScrollView, ActivityIndicator } from "react-native"
import { useNavigation, useRoute } from "@react-navigation/native"
import { scale } from "react-native-size-matters"
import { useAppDispatch, useAppSelector } from "app/redux/hooks"

//Local Imports
import { Button } from "app/components"
import CapsuleView from "./CapsuleView"
import { colors, typography } from "app/theme"
import MainHeader from "app/components/MainHeader"
import { DropdownComponent, EmptyComponent } from "app/components/DropDownComponent"
import { getEtheraClients, getClientServices } from "app/services/apis/client"
import {
  addServices,
  removeSelectedClients,
  removeServices,
  resetAppointmentLocationScreen,
  setAppointmentDate,
  setBookingId,
  setAppointmentLoader,
  setClients,
  setEndTime,
  setError,
  setSelectedClients,
  setServices,
  setStartTime,
  setHealthCheckBox,
  setZoomCheckBox,
  setMeetCheckBox,
} from "app/redux/slices/createAppointmentSlice"
import {
  createBooking,
  createAppointmentWithBooking,
  createAppointmentWithoutBooking,
  deleteAppointmentBooking,
} from "app/services/apis/createAppointment"
import {
  generateBodyWithOutBooking,
  generateBodyWithBooking,
  generateBookingBody,
} from "app/services/helperFunctions/generateBody"
import { SelectOptionButton } from "app/components/SelectableOption"
import { AntDesign } from "@expo/vector-icons"
import dayjs from "dayjs"
import DatePicker from "react-native-date-picker"
import { showFlashMessage } from "app/services/helperFunctions/showFlashMsg"
import CheckBoxComponent from "app/components/CheckBox"
import TeleHealthView from "./TeleHealthView"

export const AppointmentDetails = () => {
  //Hooks
  const dispatch = useAppDispatch()
  const navigation = useNavigation()
  const route = useRoute()

  const appointmentState = useAppSelector((state) => state?.createAppointment)
  const selectedClientIds = appointmentState?.allSelectedClients?.map((client) => client.id)

  const filteredClients = appointmentState?.clients?.filter(
    (client) => !selectedClientIds.includes(client.id),
  )

  //Local States
  const [clientName, setClientName] = useState("")
  const [clientId, setClientId] = useState(0)
  const [servicesloader, setServicesLoader] = useState(false)
  const [clientsloader, setClientsLoader] = useState(false)
  const [serviceError, setServiceError] = useState<string>("")
  const [minEndTime, setMinEndTime] = useState(new Date())

  const [dates, setDates] = useState({
    //This state is playing with DatePicker
    show: false,
    type: "",
    date: "",
    start: "",
    end: "",
  })

  const $bottomContainerInsets = useSafeAreaInsetsStyle(["bottom", "top"])

  const onPressCreateAppointment = () => {
    if (appointmentState?.appointmentLocationType === "other") {
      if (
        appointmentState?.allSelectedClients?.length === 0 ||
        !appointmentState?.startTime ||
        !appointmentState?.endTime
      ) {
        dispatch(setError("is required"))
        return
      } else if (
        appointmentState?.allSelectedClients?.some((element) => !element?.services?.length)
      ) {
        setServiceError("Select service with each client")
        return
      } else {
        dispatch(setError(""))
        let body = generateBodyWithOutBooking(appointmentState)
        dispatch(setAppointmentLoader(true))
        //@ts-ignore
        createAppointmentWithoutBooking(body) // creating appointment with other location no booking needed
          .then((response: any) => {
            dispatch(setAppointmentLoader(false))
            if (response?.code === 201 || response?.code === 200) {
              console.log("Appointment WithOut Booking success")
              dispatch(resetAppointmentLocationScreen())
              // @ts-ignore
              navigation.navigate("Appointments")
            } else if (response?.code === 400) {
              //TODO error array an object correction
              let errorKey = Object.keys(response?.message)[0]
              let errorMessage = response?.message[errorKey]
              console.log("error in create Appointment Without Booking ")
              showFlashMessage(errorMessage, "warning", colors?.green, colors?.black)
            }
          })

          .catch((error) => {
            console.log("error", error), dispatch(setAppointmentLoader(false))
          })
      }
    } else {
      if (!appointmentState?.startTime || !appointmentState?.endTime) {
        dispatch(setError("is required"))
      } else if (
        appointmentState?.allSelectedClients?.some((element) => !element?.services?.length)
      ) {
        setServiceError("Select service with each client ")
      } else {
        dispatch(setError(""))

        let body = generateBookingBody(appointmentState)
        dispatch(setAppointmentLoader(true))
        //@ts-ignore
        createBooking(body) // creating booking as selected location is ethera
          .then((result: any) => {
            if (result?.code === 201 || result?.code === 200) {
              dispatch(setAppointmentLoader(false))
              console.log("Booking created successfully")
              let bookingId = result?.data?.id
              dispatch(setBookingId({ bookingId: result?.data?.id }))
              let params = generateBodyWithBooking(appointmentState, bookingId)
              createAppointmentWithBooking(params) // in createBookingSucces creating appointment with respective booking
                .then((response: any) => {
                  if (response?.code === 201 || response?.code === 200) {
                    console.log(" AppointmentWithBooking success")
                    dispatch(resetAppointmentLocationScreen())
                    // @ts-ignore
                    navigation.navigate("Appointments")
                  } else {
                    console.log(" AppointmentWithBooking error")
                    deleteAppointmentBooking(bookingId) //in create appointment failure case deleting the booking
                      .then((res: any) => {
                        if (res.code == 204) {
                          console.log("Booking Deleted successfull")
                          //TODO error array an object correction && Delete booking Api call
                          let errorKey = Object.keys(response?.message)[0]
                          let errorMessage = response?.message[errorKey]
                          showFlashMessage(errorMessage, "warning", colors?.green, colors?.black)
                        } else {
                          console.log("Booking Deleted error", res)
                        }
                      })
                      .catch((error: any) => {
                        console.log("error in Booking Delete", error)
                      })
                  }
                })
                .catch((error: any) => {
                  console.log("error here createBooking", error)
                  dispatch(resetAppointmentLocationScreen())
                })
            } else {
              dispatch(setAppointmentLoader(false))
              console.log("result in createBooking error", JSON.stringify(result, null, 2))
              //TODO error array an object correction
              let errorKey = Object.keys(result?.message)[0]
              let errorMessage = result?.message[errorKey]
              dispatch(setError(""))
              showFlashMessage(errorMessage, "warning", colors?.green, colors?.black)
            }
          })
          .catch((error: any) => {
            dispatch(setAppointmentLoader(false))
            console.log("error here", error)
          })
      }
    }
  }

  const handleRemoveClient = (clientToRemove: any) => {
    setServiceError("")
    dispatch(setServices([]))

    const updatedSelectedClients = appointmentState?.allSelectedClients?.filter(
      (client) => client.id !== clientToRemove,
    )
    dispatch(removeSelectedClients(updatedSelectedClients))
    if (!updatedSelectedClients?.length) {
      dispatch(setServices([]))
    }
  }

  const handleRemoveService = (element: any, serviceToRemove: any) => {
    const updatedArray = appointmentState?.allSelectedClients?.map((client) => {
      if (client?.id === element?.id) {
        const updatedServices = client?.services?.filter(
          (service) => service?.id !== serviceToRemove,
        )
        return {
          ...client,
          services: updatedServices,
        }
      }
      return client
    })
    dispatch(removeServices(updatedArray))
  }

  const onPressHealthCheckBox = (newValue: any) => {
    dispatch(setHealthCheckBox(newValue))
  }

  const onPressZoomCheckBox = (newValue: any) => {
    dispatch(setZoomCheckBox(newValue))
  }

  const onPressMeetCheckBox = (newValue: any) => {
    dispatch(setMeetCheckBox(newValue))
  }

  useEffect(() => {
    if (!appointmentState?.clients?.length) {
      setClientsLoader(true)
      getEtheraClients()
        .then((result: any) => {
          setClientsLoader(false)
          dispatch(setClients(result?.data))
        })
        .catch((error: any) => {
          setClientsLoader(false)
          console.log("error in fetching clients", error)
        })
    }
  }, [])

  useEffect(() => {
    if (clientName !== "") {
      setServicesLoader(true)
      getClientServices({ clientId: appointmentState?.selectedClient?.id })
        .then((result: any) => {
          dispatch(setServices(result?.data))
          setServicesLoader(false)
        })
        .catch((error: any) => {
          setServicesLoader(false)
          console.log("error in fetching servics", error)
        })
    }
  }, [clientName])

  return (
    <View style={[$container, $bottomContainerInsets]}>
      <MainHeader />
      <View style={styles.infoContainer}>
        <Text style={styles.infoText}>Appointment Details</Text>
      </View>
      <ScrollView style={{ flex: 1 }} contentContainerStyle={{ paddingHorizontal: 20 }}>
        <>
          <View
            style={{ flexDirection: "row", flex: 1, marginTop: scale(5), alignItems: "center" }}
          >
            <CheckBoxComponent
              value={appointmentState?.healthCheckBox}
              onValueChange={(newValue) => onPressHealthCheckBox(newValue)}
            />
            <Text
              style={{
                fontSize: scale(13),
                color: colors.black,
                marginLeft: scale(15),
                fontWeight: "600",
              }}
            >
              TeleHealth
            </Text>
          </View>
          {appointmentState?.healthCheckBox && (
            <TeleHealthView
              onPressMeetCheckBox={onPressMeetCheckBox}
              onPressZoomCheckBox={onPressZoomCheckBox}
            />
          )}

          <View style={{ paddingTop: 5, flexDirection: "row" }}>
            <View style={{ flex: 1, marginRight: 5 }}>
              <Text style={styles.label}>Start Time</Text>
              <SelectOptionButton
                selectedText={
                  appointmentState?.startTime ? appointmentState?.startTime : "Start Time"
                }
                onPress={() => {
                  appointmentState?.endTime && dispatch(setEndTime(""))
                  setDates((prev) => {
                    return {
                      ...prev,
                      type: "start",
                      show: true,
                    }
                  })
                }}
                icon={<AntDesign name="calendar" size={24} color="black" />}
              />
            </View>
            <View style={{ flex: 1, marginLeft: 5 }}>
              <Text style={styles.label}>End Time</Text>
              <SelectOptionButton
                selectedText={appointmentState?.endTime ? appointmentState?.endTime : "End Time"}
                onPress={() =>
                  setDates((prev) => {
                    return {
                      ...prev,
                      type: "end",
                      show: !prev?.show,
                    }
                  })
                }
                icon={<AntDesign name="calendar" size={24} color="black" />}
              />
            </View>
          </View>
          {appointmentState?.error &&
          (!appointmentState?.startTime || !appointmentState?.endTime) ? (
            <Text style={{ color: "red", marginTop: scale(2) }}>
              Time {appointmentState?.error}
            </Text>
          ) : null}
        </>
        <View style={{ paddingTop: 5 }}>
          {appointmentState?.allSelectedClients?.map((element, index) => {
            return (
              <CapsuleView
                key={index}
                element={element}
                handleRemoveClient={handleRemoveClient}
                handleRemoveService={handleRemoveService}
              />
            )
          })}
          {serviceError ? (
            <Text style={{ color: "red", marginTop: scale(4) }}>{serviceError}</Text>
          ) : null}
        </View>

        <View style={{ paddingVertical: 5 }}>
          <Text style={styles.label}>Clients</Text>
          {clientsloader ? (
            <View style={styles.container}>
              <ActivityIndicator color={colors.orange} />
            </View>
          ) : (
            <>
              {filteredClients?.length !== 0 ? (
                <DropdownComponent
                  search
                  searchPlaceholder="Search Client"
                  placeholder="Name"
                  onChange={(text) => {
                    dispatch(setError(""))
                    setClientName(text.label), setClientId(text.value)
                    dispatch(
                      setSelectedClients({
                        name: text.label,
                        id: text.value,
                      }),
                    )
                  }}
                  data={filteredClients?.map(
                    (client: {
                      first_name: string
                      middle_name: string
                      last_name: string
                      id: string
                    }) => ({
                      label: `${client?.first_name}${
                        client?.middle_name !== null ? client?.middle_name : ""
                      } ${client?.last_name}`,
                      value: client?.id,
                    }),
                  )}
                />
              ) : (
                <EmptyComponent title="No Clients Found" />
              )}
            </>
          )}
        </View>

        {appointmentState?.error &&
        appointmentState?.appointmentLocationType === "other" &&
        appointmentState?.allSelectedClients?.length === 0 ? (
          <Text style={{ color: "red", marginTop: scale(4) }}>Select atleast one client</Text>
        ) : null}

        <View style={{ paddingVertical: 5 }}>
          <Text style={styles.label}>Services</Text>
          {servicesloader === true ? (
            <View style={styles.container}>
              <ActivityIndicator color={colors.orange} />
            </View>
          ) : (
            <>
              {appointmentState?.services?.length !== 0 ? (
                <DropdownComponent
                  placeholder="Services"
                  onChange={(text) => {
                    setServiceError("")
                    dispatch(
                      addServices({
                        id: clientId,
                        services: {
                          id: text?.value,
                          name: text?.label,
                          fee: text?.fee,
                        },
                      }),
                    )
                  }}
                  data={appointmentState?.services?.map((element) => ({
                    label: element?.service?.service,
                    value: element?.service?.id,
                    fee: element?.service?.fee,
                  }))}
                />
              ) : (
                <EmptyComponent title="No Services Found" />
              )}
            </>
          )}
        </View>

        <View style={{ marginVertical: 44 }}>
          <Button
            text="Back"
            textStyle={{ color: colors.black }}
            onPress={() => {
              navigation.goBack()
            }}
            style={{ borderColor: colors.border, borderWidth: 1, marginVertical: scale(5) }}
          />
          <Button
            preset="filled"
            text="Create Appointment"
            onPress={onPressCreateAppointment}
            loading={appointmentState?.appointmentLoader}
          />

          <Button
            text="Cancel"
            textStyle={{ color: colors.brown }}
            onPress={() => {
              dispatch(resetAppointmentLocationScreen()),
                // @ts-ignore
                navigation.navigate("Appointments")
            }}
          />
        </View>
      </ScrollView>
      <DatePicker
        locale="en"
        modal
        mode={dates.type === "date" ? "date" : "time"}
        open={dates.show}
        date={new Date()}
        minuteInterval={15}
        minimumDate={
          (appointmentState?.appointmentLocationType === "ethera" &&
            dates.type === "start" &&
            //@ts-ignore
            route?.params?.minimumTime) ||
          (appointmentState?.appointmentLocationType === "ethera" &&
            dates.type === "end" &&
            //@ts-ignore
            route?.params?.minimumTime) ||
          (appointmentState?.appointmentLocationType === "other" &&
            dates.type === "end" &&
            minEndTime)
        }
        maximumDate={
          appointmentState?.appointmentLocationType === "ethera" &&
          dates.type === "end" &&
          //@ts-ignore
          route?.params?.maximumDate
        }
        onConfirm={(date) => {
          let formatedTime = dayjs(new Date(date)).format("h:mm A")

          if (dates.type === "start") {
            dispatch(setStartTime({ startTime: formatedTime }))
            setMinEndTime(date)
            setDates((prev) => {
              return {
                ...prev,
                start: formatedTime,
                type: "",
                show: false,
              }
            })
          }

          if (dates.type === "end") {
            dispatch(setEndTime({ endTime: formatedTime }))
            setDates((prev) => {
              return {
                ...prev,
                end: formatedTime,
                type: "",
                show: false,
              }
            })
          }
        }}
        onCancel={() => {
          setDates((prev) => {
            return {
              ...prev,
              show: false,
            }
          })
        }}
      />
    </View>
  )
}

const $container: ViewStyle = {
  flex: 1,
  backgroundColor: colors.background,
}

const styles = StyleSheet.create({
  infoContainer: {
    marginVertical: 24,
    borderTopRightRadius: 10,
    borderBottomRightRadius: 10,
    backgroundColor: colors.lightGrey2,
    width: 200,
    paddingLeft: 20,
    height: 44,
    justifyContent: "center",
  },
  infoText: {
    fontSize: 14,
    fontFamily: typography.fonts.spaceGrotesk.bold,
    color: colors.black,
  },
  label: { marginVertical: 5, color: colors.grey },
  container: {
    height: 48,
    borderColor: colors.border,
    borderWidth: StyleSheet.hairlineWidth * 2,
    borderRadius: 4,
    backgroundColor: colors.white,
    paddingTop: 15,
  },
})
